<template>
  <div class="form-builder">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      :label-width="labelWidth"
      :size="size"
      @submit.prevent="handleSubmit"
    >
      <el-row :gutter="rowGutter">
        <el-col 
          v-for="field in formFields" 
          :key="field.name"
          :span="field.span || defaultSpan"
          :offset="field.offset || 0"
        >
          <el-form-item 
            :label="field.label" 
            :prop="field.name"
            :required="field.required"
          >
            <!-- 输入框 -->
            <el-input
              v-if="field.type === 'input'"
              v-model="formData[field.name]"
              :placeholder="field.placeholder"
              :type="field.inputType || 'text'"
              :maxlength="field.maxlength"
              :show-word-limit="field.showWordLimit"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
              :prefix-icon="field.prefixIcon"
              :suffix-icon="field.suffixIcon"
            />
            
            <!-- 文本域 -->
            <el-input
              v-else-if="field.type === 'textarea'"
              v-model="formData[field.name]"
              type="textarea"
              :placeholder="field.placeholder"
              :rows="field.rows || 3"
              :maxlength="field.maxlength"
              :show-word-limit="field.showWordLimit"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
            />
            
            <!-- 选择器 -->
            <el-select
              v-else-if="field.type === 'select'"
              v-model="formData[field.name]"
              :placeholder="field.placeholder"
              :multiple="field.multiple"
              :filterable="field.filterable"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
              :style="{ width: '100%' }"
            >
              <el-option
                v-for="option in field.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
                :disabled="option.disabled"
              />
            </el-select>
            
            <!-- 日期选择器 -->
            <el-date-picker
              v-else-if="field.type === 'date'"
              v-model="formData[field.name]"
              :type="field.dateType || 'date'"
              :placeholder="field.placeholder"
              :format="field.format"
              :value-format="field.valueFormat"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
              :style="{ width: '100%' }"
            />
            
            <!-- 时间选择器 -->
            <el-time-picker
              v-else-if="field.type === 'time'"
              v-model="formData[field.name]"
              :placeholder="field.placeholder"
              :format="field.format || 'HH:mm:ss'"
              :value-format="field.valueFormat || 'HH:mm:ss'"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
              :style="{ width: '100%' }"
            />
            
            <!-- 数字输入框 -->
            <el-input-number
              v-else-if="field.type === 'number'"
              v-model="formData[field.name]"
              :placeholder="field.placeholder"
              :min="field.min"
              :max="field.max"
              :step="field.step || 1"
              :precision="field.precision"
              :controls="field.controls !== false"
              :disabled="field.disabled"
              :style="{ width: '100%' }"
            />
            
            <!-- 开关 -->
            <el-switch
              v-else-if="field.type === 'switch'"
              v-model="formData[field.name]"
              :active-text="field.activeText"
              :inactive-text="field.inactiveText"
              :active-value="field.activeValue !== undefined ? field.activeValue : true"
              :inactive-value="field.inactiveValue !== undefined ? field.inactiveValue : false"
              :disabled="field.disabled"
            />
            
            <!-- 单选框组 -->
            <el-radio-group
              v-else-if="field.type === 'radio'"
              v-model="formData[field.name]"
              :disabled="field.disabled"
            >
              <el-radio
                v-for="option in field.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-radio>
            </el-radio-group>
            
            <!-- 复选框组 -->
            <el-checkbox-group
              v-else-if="field.type === 'checkbox'"
              v-model="formData[field.name]"
              :disabled="field.disabled"
            >
              <el-checkbox
                v-for="option in field.options"
                :key="option.value"
                :label="option.value"
                :disabled="option.disabled"
              >
                {{ option.label }}
              </el-checkbox>
            </el-checkbox-group>
            
            <!-- 滑块 -->
            <el-slider
              v-else-if="field.type === 'slider'"
              v-model="formData[field.name]"
              :min="field.min || 0"
              :max="field.max || 100"
              :step="field.step || 1"
              :show-tooltip="field.showTooltip !== false"
              :range="field.range"
              :disabled="field.disabled"
            />
            
            <!-- 评分 -->
            <el-rate
              v-else-if="field.type === 'rate'"
              v-model="formData[field.name]"
              :max="field.max || 5"
              :show-score="field.showScore"
              :show-text="field.showText"
              :texts="field.texts"
              :disabled="field.disabled"
            />
            
            <!-- 颜色选择器 -->
            <el-color-picker
              v-else-if="field.type === 'color'"
              v-model="formData[field.name]"
              :show-alpha="field.showAlpha"
              :disabled="field.disabled"
            />
            
            <!-- 文件上传 -->
            <el-upload
              v-else-if="field.type === 'upload'"
              v-model:file-list="formData[field.name]"
              :action="field.uploadUrl"
              :headers="field.headers"
              :data="field.uploadData"
              :multiple="field.multiple"
              :accept="field.accept"
              :limit="field.limit"
              :file-list="field.fileList || []"
              :auto-upload="field.autoUpload !== false"
              :drag="field.drag"
              :list-type="field.listType || 'text'"
              :show-file-list="field.showFileList !== false"
              :disabled="field.disabled"
              @change="handleUploadChange"
              @success="handleUploadSuccess"
              @error="handleUploadError"
            >
              <template #default>
                <div v-if="field.drag" class="upload-drag-area">
                  <el-icon size="48" color="#c0c4cc"><Upload /></el-icon>
                  <p>将文件拖到此处，或<em>点击上传</em></p>
                </div>
                <el-button v-else type="primary">
                  <el-icon><Upload /></el-icon>
                  {{ field.uploadText || '点击上传' }}
                </el-button>
              </template>
            </el-upload>
            
            <!-- 自定义插槽 -->
            <slot
              v-else-if="field.type === 'custom'"
              :name="field.slotName"
              :field="field"
              :value="formData[field.name]"
              :update="(value: any) => updateFieldValue(field.name, value)"
            />
            
            <!-- 默认输入框 -->
            <el-input
              v-else
              v-model="formData[field.name]"
              :placeholder="field.placeholder"
              :clearable="field.clearable !== false"
              :disabled="field.disabled"
            />
          </el-form-item>
        </el-col>
      </el-row>
      
      <!-- 表单操作按钮 -->
      <div v-if="showActions" class="form-actions">
        <el-button 
          v-if="showSubmit"
          type="primary" 
          :loading="submitLoading"
          @click="handleSubmit"
        >
          {{ submitText }}
        </el-button>
        <el-button 
          v-if="showReset"
          @click="handleReset"
        >
          {{ resetText }}
        </el-button>
        <el-button 
          v-if="showCancel"
          @click="handleCancel"
        >
          {{ cancelText }}
        </el-button>
        <slot name="actions" />
      </div>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, nextTick } from 'vue'
import { Upload } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'

// 表单字段类型定义
interface FormField {
  name: string
  label: string
  type: 'input' | 'textarea' | 'select' | 'date' | 'time' | 'number' | 'switch' | 'radio' | 'checkbox' | 'slider' | 'rate' | 'color' | 'upload' | 'custom'
  required?: boolean
  span?: number
  offset?: number
  placeholder?: string
  disabled?: boolean
  clearable?: boolean
  
  // 输入框相关
  inputType?: string
  maxlength?: number
  showWordLimit?: boolean
  prefixIcon?: string
  suffixIcon?: string
  
  // 文本域相关
  rows?: number
  
  // 选择器相关
  options?: Array<{ label: string; value: any; disabled?: boolean }>
  multiple?: boolean
  filterable?: boolean
  
  // 日期相关
  dateType?: string
  format?: string
  valueFormat?: string
  
  // 时间相关
  timeFormat?: string
  timeValueFormat?: string
  
  // 数字相关
  min?: number
  max?: number
  step?: number
  precision?: number
  controls?: boolean
  
  // 开关相关
  activeText?: string
  inactiveText?: string
  activeValue?: any
  inactiveValue?: any
  
  // 滑块相关
  range?: boolean
  showTooltip?: boolean
  
  // 评分相关
  max?: number
  showScore?: boolean
  showText?: boolean
  texts?: string[]
  
  // 颜色相关
  showAlpha?: boolean
  
  // 上传相关
  uploadUrl?: string
  headers?: Record<string, string>
  uploadData?: Record<string, any>
  multiple?: boolean
  accept?: string
  limit?: number
  fileList?: any[]
  autoUpload?: boolean
  drag?: boolean
  listType?: string
  showFileList?: boolean
  uploadText?: string
  
  // 自定义相关
  slotName?: string
  
  // 验证规则
  rules?: any[]
}

// 组件属性
interface Props {
  fields: FormField[]
  modelValue?: Record<string, any>
  rules?: Record<string, any>
  labelWidth?: string | number
  size?: 'large' | 'default' | 'small'
  rowGutter?: number
  defaultSpan?: number
  showActions?: boolean
  showSubmit?: boolean
  showReset?: boolean
  showCancel?: boolean
  submitText?: string
  resetText?: string
  cancelText?: string
  submitLoading?: boolean
}

// 组件事件
interface Emits {
  (e: 'update:modelValue', value: Record<string, any>): void
  (e: 'submit', data: Record<string, any>): void
  (e: 'reset'): void
  (e: 'cancel'): void
  (e: 'upload-change', file: any, fileList: any[]): void
  (e: 'upload-success', response: any, file: any, fileList: any[]): void
  (e: 'upload-error', error: any, file: any, fileList: any[]): void
}

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => ({}),
  rules: () => ({}),
  labelWidth: '120px',
  size: 'default',
  rowGutter: 20,
  defaultSpan: 12,
  showActions: true,
  showSubmit: true,
  showReset: true,
  showCancel: false,
  submitText: '提交',
  resetText: '重置',
  cancelText: '取消',
  submitLoading: false
})

const emit = defineEmits<Emits>()

// 表单引用
const formRef = ref()

// 表单数据
const formData = reactive<Record<string, any>>({})

// 表单验证规则
const formRules = computed(() => {
  const rules: Record<string, any> = { ...props.rules }
  
  // 从字段配置中提取验证规则
  props?.fields?.forEach(field => {
    if (field.rules && field.rules.length > 0) {
      rules[field.name] = field.rules
    }
  })
  
  return rules
})

// 初始化表单数据
const initFormData = () => {
  // 清空现有数据
  Object.keys(formData).forEach(key => {
    delete formData[key]
  })
  
  // 确保 fields 存在
  if (!props.fields || !Array.isArray(props.fields)) {
    return;
  }

  // 设置初始值
  props.fields.forEach(field => {
    const value = props.modelValue[field.name]
    if (value !== undefined) {
      formData[field.name] = value
    } else {
      // 设置默认值
      switch (field.type) {
        case 'checkbox':
          formData[field.name] = []
          break
        case 'switch':
          formData[field.name] = field.inactiveValue !== undefined ? field.inactiveValue : false
          break
        case 'rate':
          formData[field.name] = 0
          break
        case 'slider':
          formData[field.name] = field.range ? [field.min || 0, field.max || 100] : field.min || 0
          break
        case 'upload':
          formData[field.name] = field.fileList || []
          break
        default:
          formData[field.name] = ''
      }
    }
  })
}

// 更新字段值
const updateFieldValue = (fieldName: string, value: any) => {
  formData[fieldName] = value
  emit('update:modelValue', { ...formData })
}

// 监听字段变化
watch(() => props.modelValue, initFormData, { deep: true, immediate: true })

// 监听字段配置变化
watch(() => props.fields, initFormData, { deep: true })

// 表单提交
const handleSubmit = async () => {
  if (!formRef.value) return
  
  try {
    await formRef.value.validate()
    emit('submit', { ...formData })
  } catch (error) {
    console.error('表单验证失败:', error)
  }
}

// 表单重置
const handleReset = () => {
  if (!formRef.value) return
  
  formRef.value.resetFields()
  initFormData()
  emit('reset')
}

// 表单取消
const handleCancel = () => {
  emit('cancel')
}

// 文件上传变化
const handleUploadChange = (file: any, fileList: any[]) => {
  emit('upload-change', file, fileList)
}

// 文件上传成功
const handleUploadSuccess = (response: any, file: any, fileList: any[]) => {
  emit('upload-success', response, file, fileList)
}

// 文件上传失败
const handleUploadError = (error: any, file: any, fileList: any[]) => {
  emit('upload-error', error, file, fileList)
}

// 暴露方法给父组件
defineExpose({
  validate: () => formRef.value?.validate(),
  resetFields: () => formRef.value?.resetFields(),
  clearValidate: (props?: string | string[]) => formRef.value?.clearValidate(props),
  scrollToField: (prop: string) => formRef.value?.scrollToField(prop),
  getFormData: () => ({ ...formData })
})
</script>

<style scoped>
.form-builder {
  width: 100%;
}

.form-actions {
  margin-top: 24px;
  text-align: center;
}

.form-actions .el-button {
  margin: 0 8px;
}

.upload-drag-area {
  text-align: center;
  padding: 20px;
  color: #606266;
}

.upload-drag-area em {
  color: #409eff;
  font-style: normal;
}

.upload-drag-area p {
  margin: 10px 0 0;
  font-size: 14px;
}
</style>
